/**
 ******************************************************************************
 * @file           : bsp_can_config.h
 * @brief          : CAN Configuration File (STM32F4xx)
 ******************************************************************************
 * @attention
 *
 * CAN配置文件
 * 支持CAN1和CAN2
 *
 ******************************************************************************
 */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BSP_CAN_CONFIG_H
#define __BSP_CAN_CONFIG_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/

/* ============================================================================ */
/*                       日志系统配置（改这里的数字）                             */
/* ============================================================================ */
/* 日志后端选择：1=EasyLogger, 2=printf, 0=关闭 */
#define CAN_USE_LOG     1

/* 根据配置自动定义日志宏 */
#if (CAN_USE_LOG == 1)
    /* 使用EasyLogger */
    #ifndef LOG_TAG
        #define LOG_TAG    "CAN"
    #endif
    #include "elog.h"
    
#elif (CAN_USE_LOG == 2)
    /* 使用printf */
    #include <stdio.h>
    #define log_i(fmt, ...)     printf(fmt "\r\n", ##__VA_ARGS__)
    #define log_w(fmt, ...)     printf("[WARN] " fmt "\r\n", ##__VA_ARGS__)
    #define log_e(fmt, ...)     printf("[ERROR] " fmt "\r\n", ##__VA_ARGS__)
    #define log_d(fmt, ...)     printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__)
    
#else
    /* 关闭日志 */
    #define log_i(fmt, ...)
    #define log_w(fmt, ...)
    #define log_e(fmt, ...)
    #define log_d(fmt, ...)
#endif

/* ============================================================================ */
/*                      CAN选择配置（改这里即可切换CAN）                         */
/* ============================================================================ */
/**
 * @brief CAN选择（1~2）
 * 
 * STM32F4 CAN资源：
 *   CAN1: 主CAN，独立使用或作为CAN2的主控
 *   CAN2: 从CAN，必须先使能CAN1
 * 
 * 引脚：
 *   CAN1: TX=PA12/PB9/PD1, RX=PA11/PB8/PD0 (AF9)
 *   CAN2: TX=PB6/PB13, RX=PB5/PB12 (AF9)
 */
#define CAN_SELECT_NUM          1       /*!< 选择使用的CAN号 */

/**
 * @brief CAN引脚选择
 * 
 * 0 = 默认引脚组
 * 1 = 备用引脚组
 */
#define CAN_PIN_SELECT          0       /*!< 引脚选择 */

/**
 * @brief CAN波特率配置
 * 
 * 常用波特率：
 *   125kbps（推荐，长距离）
 *   250kbps
 *   500kbps
 *   1Mbps（短距离）
 * 
 * 修改此值可快速切换波特率
 */
#define CAN_BAUDRATE            500000  /*!< CAN波特率 */

/**
 * @brief CAN工作模式
 * 
 * 0 = 正常模式（Normal）
 * 1 = 环回模式（Loopback，自测试）
 * 2 = 静默模式（Silent，只接收）
 * 3 = 环回静默模式（Loopback+Silent）
 */
#define CAN_MODE                0       /*!< CAN工作模式 */

/**
 * @brief 接收FIFO选择
 * 
 * 0 = FIFO0
 * 1 = FIFO1
 */
#define CAN_RX_FIFO             0       /*!< 接收FIFO */

/* ============================================================================ */
/*                    自动配置区域（请勿手动修改）                                */
/* ============================================================================ */

/* CAN模式宏定义 */
#if (CAN_MODE == 0)
    #define CAN_MODE_CONFIG         CAN_MODE_NORMAL
#elif (CAN_MODE == 1)
    #define CAN_MODE_CONFIG         CAN_MODE_LOOPBACK
#elif (CAN_MODE == 2)
    #define CAN_MODE_CONFIG         CAN_MODE_SILENT
#elif (CAN_MODE == 3)
    #define CAN_MODE_CONFIG         CAN_MODE_SILENT_LOOPBACK
#else
    #error "Invalid CAN_MODE, please select 0~3"
#endif

/* CAN FIFO宏定义 */
#if (CAN_RX_FIFO == 0)
    #define CAN_RX_FIFO_CONFIG      CAN_RX_FIFO0
    #define CAN_IT_RX_CONFIG        CAN_IT_RX_FIFO0_MSG_PENDING
#else
    #define CAN_RX_FIFO_CONFIG      CAN_RX_FIFO1
    #define CAN_IT_RX_CONFIG        CAN_IT_RX_FIFO1_MSG_PENDING
#endif

/* --------------------------------------------------------------------------- */
/* CAN1 配置 (PA11/PA12 或 PB8/PB9)  AF9                                       */
/* --------------------------------------------------------------------------- */
#if (CAN_SELECT_NUM == 1)
    #define CAN_CANx                        CAN1
    #define CAN_CANx_CLK_ENABLE()           __HAL_RCC_CAN1_CLK_ENABLE()
    #define CAN_CANx_RX_IRQn                CAN1_RX0_IRQn
    #define CAN_CANx_TX_IRQn                CAN1_TX_IRQn
    #define CAN_CANx_RX_IRQHandler          CAN1_RX0_IRQHandler
    #define CAN_CANx_TX_IRQHandler          CAN1_TX_IRQHandler
    #define CAN_GPIO_AF                     GPIO_AF9_CAN1
    
    #if (CAN_PIN_SELECT == 0)  /* PA11/PA12 */
        #define CAN_TX_GPIO_PORT                GPIOA
        #define CAN_TX_GPIO_PIN                 GPIO_PIN_12
        #define CAN_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
        
        #define CAN_RX_GPIO_PORT                GPIOA
        #define CAN_RX_GPIO_PIN                 GPIO_PIN_11
        #define CAN_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()
    #else  /* PB8/PB9 */
        #define CAN_TX_GPIO_PORT                GPIOB
        #define CAN_TX_GPIO_PIN                 GPIO_PIN_9
        #define CAN_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
        
        #define CAN_RX_GPIO_PORT                GPIOB
        #define CAN_RX_GPIO_PIN                 GPIO_PIN_8
        #define CAN_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
    #endif

/* --------------------------------------------------------------------------- */
/* CAN2 配置 (PB5/PB6 或 PB12/PB13)  AF9                                       */
/* --------------------------------------------------------------------------- */
#elif (CAN_SELECT_NUM == 2)
    #define CAN_CANx                        CAN2
    #define CAN_CANx_CLK_ENABLE()           do{ __HAL_RCC_CAN1_CLK_ENABLE(); \
                                                __HAL_RCC_CAN2_CLK_ENABLE(); }while(0)
    #define CAN_CANx_RX_IRQn                CAN2_RX0_IRQn
    #define CAN_CANx_TX_IRQn                CAN2_TX_IRQn
    #define CAN_CANx_RX_IRQHandler          CAN2_RX0_IRQHandler
    #define CAN_CANx_TX_IRQHandler          CAN2_TX_IRQHandler
    #define CAN_GPIO_AF                     GPIO_AF9_CAN2
    
    #if (CAN_PIN_SELECT == 0)  /* PB5/PB6 */
        #define CAN_TX_GPIO_PORT                GPIOB
        #define CAN_TX_GPIO_PIN                 GPIO_PIN_6
        #define CAN_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
        
        #define CAN_RX_GPIO_PORT                GPIOB
        #define CAN_RX_GPIO_PIN                 GPIO_PIN_5
        #define CAN_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
    #else  /* PB12/PB13 */
        #define CAN_TX_GPIO_PORT                GPIOB
        #define CAN_TX_GPIO_PIN                 GPIO_PIN_13
        #define CAN_TX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
        
        #define CAN_RX_GPIO_PORT                GPIOB
        #define CAN_RX_GPIO_PIN                 GPIO_PIN_12
        #define CAN_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOB_CLK_ENABLE()
    #endif

#else
    #error "Invalid CAN_SELECT_NUM, please select 1~2"
#endif

/* Exported macro ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

#ifdef __cplusplus
}
#endif

#endif /* __BSP_CAN_CONFIG_H */
